package com.cd.learn.cdlearn.algorithm.util;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

/**
 * @Author: seven
 * @Date: 2021/4/29 下午5:36
 * <p>
 * 算法检查对数器
 */
public abstract class CheckAlgorithmUtil {

    /**
     * 排序方法
     *
     * @param array 将要排序的数组
     */
    protected abstract void sort(int[] array);

    /**
     * 测试方法
     */
    protected void test() {
        List<int[]> ints = geterateRandomArrays(1000, 10000, 1000);
        for (int[] anInt : ints) {
            //调用排序方法
            sort(anInt);
            //检查 排好序的数组是否正确
            boolean check = check(anInt);
            if (!check) {
                System.out.println("排序算法失败！！！！");
                return;
            }
        }
    }


    /**
     * 生成一个随机数组
     *
     * @param maxSize  最大个数
     * @param maxValue 最大值
     * @return 生成的数组
     */
    public int[] generateRandomArray(int maxSize, int maxValue) {
        //产生随机数范围为[0,maxSize]
        int[] arr = new int[(int) ((maxSize + 1) * Math.random())];
        for (int i = 0; i < arr.length; i++) {
            //产生[-maxValue,maxValue]的元素
            arr[i] = (int) ((maxValue + 1) * Math.random()) - (int) (maxValue * Math.random());
        }
        return arr;
    }

    /**
     * 生成多个随机数组
     *
     * @param maxSize  数组最大长度
     * @param mzxValue 最大值
     * @param nums     几个数组
     * @return 生成的数组
     */
    public List<int[]> geterateRandomArrays(int maxSize, int mzxValue, int nums) {
        List<int[]> result = new ArrayList<>(nums);
        for (int i = 0; i < nums; i++) {
            int[] ints = generateRandomArray(maxSize, mzxValue);
            result.add(ints);
        }
        return result;
    }

    /**
     * 检查是否排序正确
     *
     * @param array 已经排好序的数组
     * @return 利用Arrays.sort方法对拷贝出的数组进行排序，且对比排序是否一致
     */
    public boolean check(int[] array) {
        int[] ints = copyArray(array);
        Arrays.sort(ints);
        return isEqual(array, ints);
    }

    /**
     * 检查两个数组是否顺序一致
     *
     * @param arr1 自己算法排序好的数组
     * @param arr2 利用java自带工具类排序好的数组
     * @return 反回两个数组对比结果
     */
    public boolean isEqual(int[] arr1, int[] arr2) {

        if ((arr1 == null && arr2 != null) || (arr1 != null && arr2 == null)) {
            return false;
        }
        if (arr1 == null) {
            return true;
        }
        if (arr1.length != arr2.length) {
            return false;
        }
        for (int i = 0; i < arr1.length; i++) {
            if (arr1[i] != arr2[i]) {
                print(arr1);
                System.out.println();
                print(arr2);
                return false;
            }
        }
        return true;
    }


    /**
     * 遍历打印
     *
     * @param array 想要打印的数组
     */
    public static void print(int[] array) {
        for (int j : array) {
            System.out.print(j + "    ");
        }
    }

    /**
     * 拷贝数组
     *
     * @param arr 要复制的数组
     * @return 返回数组复制后的结果
     */
    public static int[] copyArray(int[] arr) {
        if (arr == null) {
            return null;
        }
        int[] res = new int[arr.length];
        System.arraycopy(arr, 0, res, 0, arr.length);
        return res;
    }

    /**
     * 数组，交换两个下标的值
     *
     * @param array       数组
     * @param firstIndex  第一个下标
     * @param seconeIndex 第二个下标
     */
    public static void exchange(int[] array, int firstIndex, int seconeIndex) {
        //两个座标一样的话不能用下面的方法交换，也不需要交换
        if (firstIndex == seconeIndex) {
            return;
        }
        array[firstIndex] = array[firstIndex] + array[seconeIndex];
        array[seconeIndex] = array[firstIndex] - array[seconeIndex];
        array[firstIndex] = array[firstIndex] - array[seconeIndex];
    }

}
